import sys
import time
import serial
import string
import binascii
import pyqtgraph as pg
import array
import threading
import numpy as np
from queue import Queue
from scipy import signal
import torch
from eeg_resnet import Bottleneck, ResNet
import comtypes.client

## 此程序文件是模型应用程序--利用已完成学习的脑电伪迹检测模型，通过咬牙、皱眉实现PPT的上下翻页，检验此脑电伪迹状态检测方法的有效性 ##

i = 0
j=0
dd,cc = signal.butter(6, [14 / 256 * 2, 80 / 256 * 2], btype='bandpass')
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')  # 判断是否有GPU
model = ResNet().to(device)
model.load_state_dict(torch.load('4_001_9963.pth'))  # 加载我们已经训练好的模型权重文件
model.eval()
ppt_path = r'C:\Users\info\eegppt.pptx' #可以是任意想测试的ppt文件名称及路径
# 启动PowerPoint应用程序
powerpoint = comtypes.client.CreateObject("PowerPoint.Application")
powerpoint.Visible = 1  # 设置为1可以看到PowerPoint的运行
 
# 打开文档
presentation = powerpoint.Presentations.Open(ppt_path)
presentation.SlideShowSettings.Run()

def goto_next_slide(ppt_path): #向前翻页
 
    # 获取当前幻灯片
    current_slide = presentation.SlideShowWindow.View.CurrentShowPosition
 
    # 转到下一张幻灯片
    if current_slide < presentation.Slides.Count:
        current_slide += 1
        presentation.SlideShowWindow.View.GotoSlide(current_slide)
 
def goto_previous_slide(ppt_path): #向后翻页
 
    # 获取当前幻灯片
    current_slide = presentation.SlideShowWindow.View.CurrentShowPosition
 
    # 转到上一张幻灯片
    if current_slide > 1:
        current_slide -= 1
        presentation.SlideShowWindow.View.GotoSlide(current_slide)


#脑电波串口读取
def Serial():
    global i 
    while(True):
        if mSerial.inWaiting() > 0:
            datat0=mSerial.readline()
            datat=mSerial.readline()
            data=datat.decode().split(",")

            while(data[0]=='\n'):
                datat0=mSerial.readline()
                datat=mSerial.readline()
                data=datat.decode().split(",")
            if i < historyLength:
                ab_data[i]=int(data[0])+int(data[1])
                i=i+1
            else:
                ab_data[:-1] = ab_data[1:]
                ab_data[i-1]=int(data[0])+int(data[1])
        
#脑电波实时绘图
def plotData():
    global i,j

    curve1.setData(ab_data,pen = 'b')
    
    if i>1000:
        gamma_data=signal.filtfilt(dd,cc,ab_data)
        gamma_data = np.apply_along_axis(lambda x: np.abs(signal.hilbert(x)), 0,gamma_data)
        curve2.setData(gamma_data,pen = 'm')

        gamma_average = np.mean(gamma_data[i-1000:i])
        if (j>200 and gamma_data[i-96]>gamma_average*2 and gamma_data[i-96]>20):

            temp_data=gamma_data[i-129:i-1]

            td = torch.from_numpy(temp_data).float().to(device)
            Predict_output = model(td).to(device)
            _, predicted = Predict_output.max(1)
            pred_type = predicted.item()
            print(pred_type)
            if pred_type==1:
                print('皱眉',j)
                goto_next_slide(ppt_path)  #皱眉时向前翻页
                curve3.setData(temp_data,pen = 'r')            
                j=0
            if pred_type==2:
                print('咬牙',j)
                goto_previous_slide(ppt_path) #咬牙时向后翻页
                curve3.setData(temp_data,pen = 'r')            
                j=0            

        j=j+1



if __name__ == "__main__":
    app = pg.mkQApp()
    win=pg.GraphicsLayoutWidget(show=True)
    win.setWindowTitle(u"脑电波实时检测")
    win.resize(1000,700) 
    EEG1_data = array.array('i')
    historyLength = 3000    #脑电波数据长度
 
    ab_data = np.zeros(historyLength).__array__('d')
    abc_data = np.zeros(historyLength).__array__('d')
    gamma_data = np.zeros(historyLength).__array__('d')
    temp_data = np.zeros(historyLength).__array__('d')
    

    EEG1 = win.addPlot(left = 'y',buttom = 'x',title = "total")
    EEG1.setRange(xRange = [0,historyLength],yRange=[0,2500],padding = 0)
    curve1 = EEG1.plot()
    curve1.setData(abc_data)
    win.nextRow()

    EEG2 = win.addPlot(left = 'y',buttom = 'x',title = "gamma")
    EEG2.setRange(xRange = [0,historyLength],yRange=[0,300],padding = 0)
    curve2 = EEG2.plot()
    curve2.setData(gamma_data)
    win.nextRow()

    EEG3 = win.addPlot(left = 'y',buttom = 'x',title = "temp")
    EEG3.setRange(xRange = [0,historyLength],yRange=[0,300],padding = 0)
    curve3 = EEG3.plot()
    curve3.setData(temp_data)

    portx = 'COM4' #以脑环接入电脑时的虚拟串口号的实际为准
    bps = 115200
    mSerial = serial.Serial(portx, int(bps))    #打开串口
    if(mSerial.isOpen()):
        print('serial is OK')
    else:
        print("serial is ERROR")
        mSerial.close()  # 关闭端口
    th1 = threading.Thread(target=Serial)
    th1.start()
    timer = pg.QtCore.QTimer()
    timer.timeout.connect(plotData)
    timer.start(4)
    sys.exit(app.exec())
